home *** CD-ROM | disk | FTP | other *** search
/ InterCD 2001 May / may_2001.iso / intercd / root / Multimedia / ^DivX_Article / virtualdub / VirtualDub-source-1_4d / AVIPipe.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2001-03-20  |  6.3 KB  |  270 lines

  1. //    VirtualDub - Video processing and capture application
  2. //    Copyright (C) 1998-2001 Avery Lee
  3. //
  4. //    This program is free software; you can redistribute it and/or modify
  5. //    it under the terms of the GNU General Public License as published by
  6. //    the Free Software Foundation; either version 2 of the License, or
  7. //    (at your option) any later version.
  8. //
  9. //    This program is distributed in the hope that it will be useful,
  10. //    but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. //    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12. //    GNU General Public License for more details.
  13. //
  14. //    You should have received a copy of the GNU General Public License
  15. //    along with this program; if not, write to the Free Software
  16. //    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  17.  
  18. #include "VirtualDub.h"
  19.  
  20. #include <windows.h>
  21. #include <crtdbg.h>
  22.  
  23. #include "AVIPipe.h"
  24.  
  25. ///////////////////////////////
  26.  
  27. //#define AVIPIPE_PERFORMANCE_MESSAGES
  28.  
  29. //static CRITICAL_SECTION csect;
  30.  
  31. ///////////////////////////////
  32.  
  33. AVIPipe::AVIPipe(int buffers, long roundup_size) {
  34.     hEventRead        = CreateEvent(NULL,FALSE,FALSE,NULL);
  35.     hEventWrite        = CreateEvent(NULL,FALSE,FALSE,NULL);
  36.     pBuffers        = new struct AVIPipeBuffer[buffers];
  37.     num_buffers        = buffers;
  38.     round_size        = roundup_size;
  39.     cur_read        = 1;
  40.     cur_write        = 1;
  41.     finalize_state    = 0;
  42.     total_audio        = 0;
  43.  
  44.     if (pBuffers)
  45.         memset((void *)pBuffers, 0, sizeof(struct AVIPipeBuffer)*buffers);
  46.  
  47.     InitializeCriticalSection(&critsec);
  48. }
  49.  
  50. AVIPipe::~AVIPipe() {
  51.     _RPT0(0,"AVIPipe::~AVIPipe()\n");
  52.  
  53.     DeleteCriticalSection(&critsec);
  54.  
  55.     if (pBuffers) {
  56.         for(int i=0; i<num_buffers; i++)
  57.             if (pBuffers[i].data)
  58.                 VirtualFree(pBuffers[i].data, 0, MEM_RELEASE);
  59.  
  60.         delete[] (void *)pBuffers;
  61.     }
  62.  
  63.     if (hEventRead)        CloseHandle(hEventRead);
  64.     if (hEventWrite)    CloseHandle(hEventWrite);
  65. }
  66.  
  67. BOOL AVIPipe::isOkay() {
  68.     return pBuffers && hEventRead && hEventWrite;
  69. }
  70.  
  71. BOOL AVIPipe::isFinalized() {
  72.     if (finalize_state & FINALIZE_TRIGGERED) {
  73.         finalize_state |= FINALIZE_ACKNOWLEDGED;
  74.         SetEvent(hEventRead);
  75.  
  76.         return TRUE;
  77.     }
  78.  
  79.     return FALSE;
  80. }
  81.  
  82. BOOL AVIPipe::isNoMoreAudio() {
  83.     return (finalize_state & FINALIZE_TRIGGERED) && !total_audio;
  84. }
  85.  
  86. void *AVIPipe::getWriteBuffer(long len, int *handle_ptr, DWORD timeout) {
  87.     int h;
  88.  
  89.     if (!len) ++len;
  90.     len = ((len+round_size-1) / round_size) * round_size;
  91.  
  92.     EnterCriticalSection(&critsec);
  93.  
  94.     for(;;) {
  95.  
  96.         if (finalize_state & FINALIZE_ABORTED) {
  97.             LeaveCriticalSection(&critsec);
  98.             return NULL;
  99.         }
  100.  
  101.         // look for a handle without a buffer
  102.  
  103.         for(h=0; h<num_buffers; h++)
  104.             if (!pBuffers[h].size)
  105.                 if (pBuffers[h].data = VirtualAlloc(NULL, len, MEM_COMMIT, PAGE_READWRITE)) {
  106.                     pBuffers[h].size = len;
  107. #ifdef AVIPIPE_PERFORMANCE_MESSAGES
  108.                     _RPT2(0,"Allocated #%d: %ld bytes\n", h+1, len);
  109. #endif
  110.                     break;
  111.                 }
  112.         
  113.         if (h<num_buffers) break;
  114.  
  115.         // look for a handle with a free buffer that's large enough
  116.         
  117.         for(h=0; h<num_buffers; h++)
  118.             if (!pBuffers[h].len && pBuffers[h].size>=len) break;
  119.  
  120.         if (h<num_buffers) break;
  121.  
  122.         // look for a handle with a free buffer
  123.  
  124.         for(h=0; h<num_buffers; h++)
  125.             if (!pBuffers[h].len && pBuffers[h].size) {
  126.                 VirtualFree(pBuffers[h].data, 0, MEM_RELEASE);
  127.                 pBuffers[h].data = NULL;
  128.                 pBuffers[h].size = 0;
  129.  
  130.                 if (pBuffers[h].data = VirtualAlloc(NULL, len, MEM_COMMIT, PAGE_READWRITE)) {
  131.                     pBuffers[h].size = len;
  132. #ifdef AVIPIPE_PERFORMANCE_MESSAGES
  133.                     _RPT2(0,"Reallocated #%d: %ld bytes\n", h+1, len);
  134. #endif
  135.                     break;
  136.                 }
  137.             }
  138.  
  139.         if (h<num_buffers) break;
  140.  
  141.         LeaveCriticalSection(&critsec);
  142.  
  143.         if (WAIT_TIMEOUT == WaitForSingleObject(hEventRead, timeout)) {
  144.             return NULL;
  145.         }
  146.  
  147.         EnterCriticalSection(&critsec);
  148.     }
  149.  
  150.     LeaveCriticalSection(&critsec);
  151.     *handle_ptr = h;
  152.  
  153.     return pBuffers[h].data;
  154. }
  155.  
  156. void AVIPipe::postBuffer(long len, long samples, int exdata, int h) {
  157.  
  158.     EnterCriticalSection(&critsec);
  159.  
  160.     pBuffers[h].len        = len+1;
  161.     pBuffers[h].sample    = samples;
  162.     pBuffers[h].iExdata    = exdata;
  163.     pBuffers[h].id        = cur_write++;
  164.  
  165.     if (exdata == -1) ++total_audio;
  166.  
  167.     LeaveCriticalSection(&critsec);
  168.  
  169.     SetEvent(hEventWrite);
  170.  
  171.     //    _RPT2(0,"Posted buffer %ld (ID %08lx)\n",handle,cur_write-1);
  172. }
  173.  
  174. void *AVIPipe::getReadBuffer(long *len_ptr, long *samples_ptr, int *exdata_ptr, int *handle_ptr, DWORD timeout) {
  175.     int h;
  176.  
  177.     EnterCriticalSection(&critsec);
  178.  
  179.     for(;;) {
  180. //        _RPT1(0,"Scouring buffers for ID %08lx\n",cur_read);
  181.  
  182.         for(h=0; h<num_buffers; h++) {
  183. //            _RPT2(0,"Buffer %ld: ID %08lx\n", h, lpBufferID[h]);
  184.             if (pBuffers[h].id == cur_read) break;
  185.         }
  186.  
  187.         if (h<num_buffers) break;
  188.  
  189.         if (finalize_state & SYNCPOINT_TRIGGERED) {
  190.             finalize_state |= SYNCPOINT_ACKNOWLEDGED;
  191.             finalize_state &= ~SYNCPOINT_TRIGGERED;
  192.             SetEvent(hEventRead);
  193.         }
  194.  
  195.         LeaveCriticalSection(&critsec);
  196.  
  197.         if (finalize_state & FINALIZE_TRIGGERED) {
  198.             finalize_state |= FINALIZE_ACKNOWLEDGED;
  199.  
  200.             SetEvent(hEventRead);
  201.             return NULL;
  202.         }
  203.  
  204.         if (WAIT_TIMEOUT == WaitForSingleObject(hEventWrite, timeout)) {
  205.             return NULL;
  206.         }
  207.         EnterCriticalSection(&critsec);
  208.     }
  209.  
  210. #ifdef AVIPIPE_PERFORMANCE_MESSAGES
  211.     _RPT1(0,"[#%d] ", h+1);
  212. #endif
  213.  
  214.     ++cur_read;
  215.  
  216.     LeaveCriticalSection(&critsec);
  217.  
  218.     *len_ptr        = pBuffers[h].len-1;
  219.     *samples_ptr    = pBuffers[h].sample;
  220.     *exdata_ptr        = pBuffers[h].iExdata;
  221.     *handle_ptr        = h;
  222.  
  223.     return pBuffers[h].data;
  224. }
  225.  
  226. void AVIPipe::releaseBuffer(int handle) {
  227.  
  228.     EnterCriticalSection(&critsec);
  229.  
  230.     if (pBuffers[handle].iExdata==-1)
  231.         --total_audio;
  232.     pBuffers[handle].len = 0;
  233.  
  234.     LeaveCriticalSection(&critsec);
  235.  
  236.     SetEvent(hEventRead);
  237. }
  238.  
  239. void AVIPipe::finalize() {
  240.     finalize_state |= FINALIZE_TRIGGERED;
  241.     SetEvent(hEventWrite);
  242.  
  243.     _RPT0(0,"AVIPipe: finalizing...\n");
  244.  
  245.     while(!(finalize_state & FINALIZE_ACKNOWLEDGED)) {
  246.         WaitForSingleObject(hEventRead, INFINITE);
  247.     }
  248.  
  249.     _RPT0(0,"AVIPipe: finalized.\n");
  250. }
  251.  
  252. void AVIPipe::abort() {
  253.     finalize_state |= FINALIZE_ABORTED;
  254.     SetEvent(hEventWrite);
  255.     SetEvent(hEventRead);
  256. }
  257.  
  258. bool AVIPipe::sync() {
  259.     finalize_state |= SYNCPOINT_TRIGGERED;
  260.     while(!(finalize_state & SYNCPOINT_ACKNOWLEDGED)) {
  261.         if (finalize_state & FINALIZE_ABORTED)
  262.             return false;
  263.  
  264.         SetEvent(hEventWrite);
  265.         WaitForSingleObject(hEventRead, INFINITE);
  266.     }
  267.     finalize_state &= ~SYNCPOINT_ACKNOWLEDGED;
  268.  
  269.     return true;
  270. }